在Compose 的 Animation 提供很多功能強大且可以擴充高階和低階的api,可以很輕鬆的實現動畫面的效果,
例如: 轉場、淡入、淡出、放大、縮小
看來一下圖,決定要使用哪個 API 實作動畫吧
if(內容變更建立動畫效果){
if(顯示與消失的動畫效果){
AnimatedVisibility()
} else {
if(狀態替換內容){
if(內容建立淡出淡入效果){
Crossfade()
}else{
AnimatedContent()
}
}else{
Modifier.animateContentSize()
}
}
} else { // 狀態顯示動畫
if(組合期間顯示動畫){
if(動畫持續顯示){
rememberInfiniteTransition()
}else{
if(同時為多個值建立動畫效果){
updateTransition()
}else{
animate*AsState()
}
}
} else {
if(精確控制動畫時間){
Animation(
(TargetBasedAnimation() || DecayAnimation())
)
} else {
if(動畫是事實的唯一來源){
Animatable()
} else {
(AnimationState() || animate())
}
}
}
}
AnimatedVisibility 可組合項以動畫方式呈現內容的顯示與消失
效果請參依 EnterTransition 和 ExitTransition 範例
https://developer.android.com/jetpack/compose/animation#enter-exit-transition
@Composable
fun Greeting(name: String) {
var visible by remember { mutableStateOf(true) }
val density = LocalDensity.current
AnimatedVisibility(
visible = visible,
//進場的效果 slideInVertically + expandVertically + fadeIn 三個效果加起來
enter = slideInVertically {
// Slide in from 40 dp from the top.
with(density) { -40.dp.roundToPx() }
} + expandVertically(
// Expand from the top.
expandFrom = Alignment.Top
) + fadeIn(
// Fade in with the initial alpha of 0.3f.
initialAlpha = 0.3f
),
//出場效果 slideOutVertically() + shrinkVertically() + fadeOut()三個效果加起來
exit = slideOutVertically() + shrinkVertically() + fadeOut()
) {
Text("Hello $name!",
Modifier.fillMaxWidth().height(200.dp),
textAlign = TextAlign.Center,
fontSize = 30.sp
)
}
}
AnimatedVisibility 新增至組合樹時立即觸發動畫
@Composable
fun Greeting(name: String) {
val state = remember {
MutableTransitionState(false).apply {
// Start the animation immediately.
targetState = true
}
}
Column {
AnimatedVisibility(visibleState = state) {
Text(text = "Hello $name!")
}
// Use the MutableTransitionState to know the current animation state
// of the AnimatedVisibility.
Text(
text = when {
state.isIdle && state.currentState -> "Visible"
!state.isIdle && state.currentState -> "Disappearing"
state.isIdle && !state.currentState -> "Invisible"
else -> "Appearing"
}
)
}
}
AnimatedVisibility (直接或間接子項) 中的內容可使用 animateEnterExit 輔助鍵為每個子項指定不同的動畫行為。
@Composable
fun Greeting(name: String) {
AnimatedVisibility(
visible = true,
enter = fadeIn(),
exit = fadeOut()
) {
// Fade in/out the background and the foreground.
Box(Modifier.fillMaxSize().background(Color.DarkGray)) {
Box(
Modifier
.align(Alignment.Center)
.animateEnterExit(
// Slide in/out the inner box.
enter = slideInVertically(),
exit = slideOutVertically()
)
.sizeIn(minWidth = 256.dp, minHeight = 64.dp)
.background(Color.Red)
) {
// Content of the notification…
}
}
}
}
AnimatedContent 可組合項可根據目標狀態產生變動時,為內容建立動畫效果。
@Composable
fun Greeting(name: String) {
Column {
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
Text("Add")
}
AnimatedContent(targetState = count) { targetCount ->
// Make sure to use `targetCount`, not `count`.
Text(text = "Count: $targetCount")
}
}
}
@Composable
fun Greeting(name: String) {
var expanded by remember { mutableStateOf(false) }
Surface(
color = MaterialTheme.colors.primary,
onClick = { expanded = !expanded }
) {
AnimatedContent(
targetState = expanded,
//modifier = Modifier.fillMaxSize(),
transitionSpec = {
fadeIn(animationSpec = tween(150, 150)) with
fadeOut(animationSpec = tween(150)) using
SizeTransform { initialSize, targetSize ->
if (targetState) {
keyframes {
// Expand horizontally first.
IntSize(targetSize.width, initialSize.height) at 150
durationMillis = 300
}
} else {
keyframes {
// Shrink vertically first.
IntSize(initialSize.width, targetSize.height) at 150
durationMillis = 300
}
}
}
}
) { targetExpanded ->
if (targetExpanded) {
//ModalBottomSheetValue.Expanded()
Text(text = "1234567890\n1234567890\n1234567890\n1234567890")
} else {
Text(text = "Hello $name!")
//ContentIcon()
//Image(painter = painterResource(id = R.mipmap.ic_launcher), contentDescription = "icon")
}
}
}
}
https://developer.android.com/jetpack/compose/animation